#ifndef SCT_RTSPSERVER_STREAMSOURCE_H
#define SCT_RTSPSERVER_STREAMSOURCE_H

#include "sct/core/common.h"
#include "sct/core/mutex.h"
#include <list>
#include "sct/rtspserver/serverinterface.h"

namespace sct
{

class CStreamSource
{
public:
	CStreamSource(CServerInterface * server);
	virtual ~CStreamSource();

	/**
	 * get the data
	 *
	 * if not data will block the routine.\n
	 * after you call this, one data in the buffer pop. so if you want
	 * to drop some data you call set p=NULL, pts=NULL, ntrunc=NULL
	 *
	 * @param p 	if available, the data write to
	 * @param len 	the max size write to
	 * @param pts	if available, the data pts write to
	 * @param ntrunc if available, the size large than len, write to
	 * @return 		the size write to p. -1 means error, 0 means EOF.
	 * @see hasdata()
	 */
	int getdata(void*p, const int len, int64_t*pts, int*ntrunc, const int force = 0);

	/**
	 * put the data
	 *
	 * the jitter of call, must not be too big or the lib work in wrong way.
	 * @param p 	the data from
	 * @param len	the data size
	 * @param pts 	the sample timestamp
	 * @see getAvgDt()
	 */
	void putdata(const void*p, const int len, const int64_t pts);

	/**
	 * set the max delay
	 *
	 * default is 300000us
	 */
	void setMaxDelay(const int d);

	/**
	 * check whether data available
	 */
	bool hasdata();

	void setName(const std::string & name);

protected:
	/**
	 * put the data to the buffer
	 *
	 * you can do something before pushing data to buffer. such as fragment stream.
	 */
	virtual void onPutData(const void*p, const int len, const int64_t pts);

private:
	class CBufferItem
	{
	public:
		uint8_t * data;
		int len;
		int64_t pts;

	public:
		static void free(CBufferItem * item)
		{
			SCT_DELETE_ARRAY(item->data);
			SCT_DELETE(item);
		}
	};

private:
	CMutex * mMutex;
	int mDelay;
	std::list<CBufferItem*> mBuffer;

	CServerInterface * mServer;

	std::string mName;
};

}//end namespace


#endif
